package com.hfut.eeg.service;

import com.hfut.eeg.common.component.EEGcache;
import com.hfut.eeg.common.eegParse.EEGDataParse;
import com.hfut.eeg.common.eegParse.Hdr;
import com.hfut.eeg.common.util.BlobListTrans;
import com.hfut.eeg.common.util.EEGUtil;
import com.hfut.eeg.dao.EEGMapper;
import com.hfut.eeg.dto.EEG;
import com.hfut.eeg.dto.EEGTrans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author 梁琦
 * @program: eeg
 * @Package com.hfut.eeg.service
 * @Description: TODO
 * @date 2019-11-22 15:19
 */
//在对EEG数据做处理的时候，做缓存，数值到达一定程度存入数据库
@Service
@Scope("singleton")
public class EEGService {

    private static final Logger LOGGER = LoggerFactory.getLogger(EEGService.class);

    @Autowired
    private EEGMapper eegMapper;

    @Autowired
    private EEGcache eeGcache;

    /**
    * @Description:
    * @param patientId 病人ID
     * @param order 需要EEG数据开始的位置
    * @return
    * @author 梁琦
    * @date 2019-12-11 10:53
    * @throws
    */
    public HashMap getEEGBySeg(String patientId,int order,int num){
        HashMap<String,Object> getReq = new HashMap<>();
        getReq.put("id",patientId);
        ArrayList<Integer> list = new ArrayList<>();
        for (int i=order;i<order+num;i++){
            list.add(i);
        }
        getReq.put("sequence",list);
        List<EEG> eeg = eegMapper.getDat(getReq);
        if(eeg==null || eeg.size()==0){
            return null;
        }
        ArrayList<ArrayList> result = new ArrayList<>();
        for (int i=0;i<16;i++){
            result.add(new ArrayList());
        }
        for (EEG trans:eeg){
            ArrayList<ArrayList>tmp = BlobListTrans.transEEGTransToList(trans);
            for (int i=0;tmp!=null&&i<tmp.size();i++){
                result.get(i).addAll(tmp.get(i));
            }
        }
        HashMap<String,Object> map = new HashMap<>();
        map.put("eeg",result);
        map.put("eegId",eeg.get(0).getEEGId());
        return map;
    }


    /**
    * 获取最新EEG数据段序号
    */
    public int getEEGLatestSequence(String patientId){
        Integer sequence = eegMapper.getEEGLatestSequence(patientId);
        return sequence==null?0:sequence;
    }

    /**
    * 获取单个EEG数据
    */
    public EEG getEEGDataSingle(HashMap<String,Object> getReq){
        HashMap<String,Object> map = new HashMap<>();
        map.put("id",getReq.get("id"));
        ArrayList<Integer> list = new ArrayList<>();
        list.add((Integer) getReq.get("sequence"));
        map.put("sequence",list);
        List<EEG>list1 = eegMapper.getDat(map);
        if(list1==null || list1.size()==0){
            return null;
        }
        return list1.get(0);
    }

    /**
    * @Description: 向数据插入eeg数据的信息，数据库中预计每个数据段保存10s钟数据，超过这个数值将会导致
     * 数据库分表操作
    * @param cache 存储的eeg信息
     * @param patientId 病人ID
    * @return eegID
    * @author 梁琦
    * @date 2019-12-16 15:35
    * @throws
    */
    public synchronized Long insertEEGData(ArrayList<ArrayList>cache,String patientId){
        Long result =-1L;
        //数据有效性检验
        if(cache==null || cache.size()<16 || patientId==null){
            return result;
        }
        if(cache.get(0).size()<500){
            LOGGER.warn("拒绝插入数据，数据量小于1秒");
            return result;
        }

        //数据库中数据段存储的数据量大小
        int storeSize = 0;
        int order = getEEGLatestSequence(patientId);

        //先从数据库获取已经存放的EEG数据段
        HashMap<String,Object> getReq = new HashMap<>();
        getReq.put("id",patientId);
        getReq.put("sequence",order);
        EEG eeg = getEEGDataSingle(getReq);
        //解析Blob，获取数据库中的数据量大小
        ArrayList<ArrayList> stores = BlobListTrans.transEEGTransToList(eeg);
        if(stores==null || stores.size()==0){
            stores = new ArrayList<>();
            storeSize = -1;
            LOGGER.error("获取SingleGuide表数据解析为空");
        }else {
            storeSize = stores.get(0).size()/500;
        }


        //存放EEG数据
        HashMap<String,Object> map = new HashMap<>();
        String []labels = eeGcache.getLabels();

        //表示数据库此时没有此eeg数据，要插入数据,或者当前记录达到存储阈值
        if(storeSize >= 10 || storeSize<0){
            for (int i = 0; i<eeGcache.getNchannel(); i++){
                map.put(labels[i],cache.get(i));
            }
            map.put("patientId",patientId);
            //利用当前时间戳作为主键
            Long eegId = System.currentTimeMillis();
            map.put("eegId",eegId);
            map.put("sequence",order+1);
            eegMapper.insertEEGExam(map);
            //表示已经有数据，要更新eeg数据
        }else {
            for (int i = 0; i<eeGcache.getNchannel(); i++){
                stores.get(i).addAll(cache.get(i));
                map.put(labels[i],stores.get(i));
            }

            map.put("sequence",order);
            map.put("eegId",eeg.getEEGId());
            eegMapper.updateEEGdata(map);
        }
        return (Long) map.get("eegId");
    }

    /**
    * 获取缩小视图的eeg
    */
    public ArrayList<ArrayList> getShrinkView(String patientId,double order,double num){
        int startSequence = (int)order;
        boolean isMiddle = order-startSequence>0;//>0表示从中间开始截取
        int mBlockNum = (int) (num/0.5);
        int BlockNum = mBlockNum%2==0?mBlockNum%2+1:mBlockNum%2+2;

        HashMap<String,Object> getReq = new HashMap<>();
        getReq.put("id",patientId);
        ArrayList<Integer> list = new ArrayList<>();
        for (int i=startSequence;i<startSequence+BlockNum;i++){
            list.add(i);
        }
        getReq.put("sequence",list);

        List<EEG> eeg = eegMapper.getDat(getReq);
        if(eeg==null || eeg.size()==0){
            return null;
        }
        ArrayList<ArrayList> result = new ArrayList<>();
        for (int i=0;i<16;i++){
            result.add(new ArrayList());
        }
        for (EEG trans:eeg){
            ArrayList<ArrayList>tmp = BlobListTrans.transEEGTransToList(trans);
            for (int i=0;tmp!=null&&i<tmp.size();i++){
                result.get(i).addAll(tmp.get(i));
            }
        }

        ArrayList<ArrayList> content = new ArrayList<>();
        //每个mBlockNum代表5秒钟的数据量
        int sumBlock = 500*mBlockNum*5;
        int start,end;
        if(isMiddle){
            start = result.get(0).size()<500*5?result.get(0).size():500*5;
            end = result.get(0).size()<500*5+sumBlock?result.get(0).size():500*5+sumBlock;
            for (ArrayList list1:result){
                content.add((ArrayList) list1.subList(start,end));
            }
        }else {
            end = result.get(0).size()<sumBlock?result.get(0).size():sumBlock;
            for (ArrayList list1:result){
                content.add((ArrayList) list1.subList(0,end));
            }
        }
        return content;
    }

    public int insertEEGList(List<EEG> eegs){
        return eegMapper.insertEEGList(eegs);
    }
}
